package utils;

import com.alibaba.druid.pool.DruidDataSourceFactory;

import javax.sql.DataSource;
import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

/**
 * @author lvtian
 * @date 2022/11/22 18:04
 */
public class DBUtils {
    private static DataSource dataSource = null;
    //初始化连接池
    static {
        Properties properties = new Properties();
        try {
            properties.load(DBUtils.class.getClassLoader().getResourceAsStream("druid.properties"));
            dataSource = DruidDataSourceFactory.createDataSource(properties);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 返回数据库连接
     * @return
     * @throws SQLException
     */
    public static Connection getConnection() throws SQLException {
        return dataSource.getConnection();
    }


    /**
     * 新增用户
     * @param sql
     * @param params
     * @return
     */
    public static int executeUpdate(String sql,Object...params){
        try(Connection connection = getConnection()){
            PreparedStatement preparedStatement = connection.prepareStatement(sql);
            for (int i = 0; i <params.length ; i++) {
                preparedStatement.setObject(i+1,params[i]);
            }
            int rows = preparedStatement.executeUpdate();
            return rows;
        } catch (Exception throwables) {
            throwables.printStackTrace();
        }
        return 0;
    }


    public static <T> List<T> executeQuery(Class<T> tClass,String sql,Object... params){
        List<T> objects = new ArrayList<>();
        try(Connection connection = getConnection()){
            PreparedStatement preparedStatement = connection.prepareStatement(sql);
            //设置占位符
            for(int i = 0;i < params.length;i++){
                preparedStatement.setObject(i + 1,params[i]);
            }
            ResultSet resultSet = preparedStatement.executeQuery();
            while(resultSet.next()){
                //实例化对象
                T obj = tClass.newInstance();
                //读取类型中的所有属性
                Field[] fields = tClass.getDeclaredFields();
                //遍历所有属性,给对象的所有属性赋值
                for(Field field : fields) {
                    //获得属性上配置的注解
                    DBField dbField = field.getDeclaredAnnotation(DBField.class);
                    //没有配置DBField注解，就读取属性名
                    if(dbField == null) {
                        //读取结果集中该列的值
                        Object value = resultSet.getObject(field.getName());
                        //将属性设置为可以访问
                        field.setAccessible(true);
                        //给属性赋值 obj.field = value
                        field.set(obj, value);
                    }else if(dbField.fieldName().length() > 0 && dbField.exists()){
                        //如果配置了DBField，并且配置了字段名 字段也存在
                        //读取结果集中该列的值
                        Object value = resultSet.getObject(dbField.fieldName());
                        field.setAccessible(true);
                        field.set(obj, value);
                    }
                }
                objects.add(obj);
            }
            return objects;
        }catch (Exception ex){
            ex.printStackTrace();
        }
        return null;
    }


    //用于查询数量的方法
    public static int executeCount(String sql,Object...params){
        try(Connection connection = getConnection()) {
            PreparedStatement preparedStatement = connection.prepareStatement(sql);
            //设置占位符
            for (int i = 0; i <params.length ; i++) {
                preparedStatement.setObject(i+1,params[i]);
            }
            ResultSet resultSet = preparedStatement.executeQuery();
            if(resultSet.next()){
                int count = resultSet.getInt(1);
                return  count;
            }
        }catch(Exception e){
            e.printStackTrace();
        }
        return 0 ;
    }
}
